package net.tanesha.recaptcha;

import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Properties;

import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaResponse;
import net.tanesha.recaptcha.http.HttpLoader;
import net.tanesha.recaptcha.http.SimpleHttpLoader;

import com.nrgedge.recaptcha.http.HttpClientProxyHttpLoader;

/**
 * Copied from net.tanesha.recaptcha.ReCaptchaImpl to allow 
 * modification of VERIFY_URL and to work around scope problems 
 * when extending ReCaptchaImpl.
 * 
 * Adds proxy support to ReCaptchaImpl
 * 
 * @author adam.galloway
 *
 */
public class ProxyReCaptchaImpl implements ReCaptcha {

	 	public static final String PROPERTY_THEME = "theme";
	 	public static final String PROPERTY_TABINDEX = "tabindex";
	 	
	 	public static final String HTTP_SERVER = "http://www.google.com/recaptcha/api";
	 	public static final String HTTPS_SERVER = "https://www.google.com/recaptcha/api";
	 	public static final String VERIFY_URL = "http://www.google.com/recaptcha/api/verify";
	 	
	 	private String privateKey;
	 	private String publicKey;
	 	private String recaptchaServer = HTTP_SERVER;
	 	private boolean includeNoscript = false;
	 	private HttpLoader httpLoader = new SimpleHttpLoader();
	 	
		public ProxyReCaptchaImpl(String proxyHost, int proxyPort, String proxyUsername, String proxyPassword) {
			super();

	        if (proxyHost != null && proxyHost.trim().length() > 0) {
	        	this.setHttpLoader(new HttpClientProxyHttpLoader(proxyHost, proxyPort, proxyUsername, proxyPassword));
	        }
		}
	 	
	 	public void setPrivateKey(String privateKey) {
	 		this.privateKey = privateKey;
	 	}
	 	public void setPublicKey(String publicKey) {
	 		this.publicKey = publicKey;
	 	}
	 	public void setRecaptchaServer(String recaptchaServer) {
	 		this.recaptchaServer = recaptchaServer;
	 	}
	 	public void setIncludeNoscript(boolean includeNoscript) {
	 		this.includeNoscript = includeNoscript;
	 	}
	 	public void setHttpLoader(HttpLoader httpLoader) {
	 		this.httpLoader  = httpLoader;
	 	}

	 	public ReCaptchaResponse checkAnswer(String remoteAddr, String challenge, String response) {

	 		String postParameters = "privatekey=" + URLEncoder.encode(privateKey) + "&remoteip=" + URLEncoder.encode(remoteAddr) +
	 			"&challenge=" + URLEncoder.encode(challenge) + "&response=" + URLEncoder.encode(response);

	 		String message = httpLoader.httpPost(VERIFY_URL, postParameters);

	 		if (message == null) {
	 			return new ReCaptchaResponse(false, "Null read from server.");
	 		}

	 		String[] a = message.split("\r?\n");
	 		if (a.length < 1) {
	 			return new ReCaptchaResponse(false, "No answer returned from recaptcha: " + message);
	 		}
	 		boolean valid = "true".equals(a[0]);
	 		String errorMessage = null;
	 		if (!valid) {
	 			if (a.length > 1)
	 				errorMessage = a[1];
	 			else
	 				errorMessage = "recaptcha4j-missing-error-message";
	 		}
	 		
	 		return new ReCaptchaResponse(valid, errorMessage);
	 	}

	 	public String createRecaptchaHtml(String errorMessage, Properties options) {

	 		String errorPart = (errorMessage == null ? "" : "&amp;error=" + URLEncoder.encode(errorMessage));

	 		String message = fetchJSOptions(options);

	 		message += "<script type=\"text/javascript\" src=\"" + recaptchaServer + "/challenge?k=" + publicKey + errorPart + "\"></script>\r\n";

	 		if (includeNoscript) {
	 			String noscript = "<noscript>\r\n" + 
	 					"	<iframe src=\""+recaptchaServer+"/noscript?k="+publicKey + errorPart + "\" height=\"300\" width=\"500\" frameborder=\"0\"></iframe><br>\r\n" + 
	 					"	<textarea name=\"recaptcha_challenge_field\" rows=\"3\" cols=\"40\"></textarea>\r\n" + 
	 					"	<input type=\"hidden\" name=\"recaptcha_response_field\" value=\"manual_challenge\">\r\n" + 
	 					"</noscript>";
	 			message += noscript;
	 		}
	 		
	 		return message;
	 	}
	 	
	 	public String createRecaptchaHtml(String errorMessage, String theme, Integer tabindex) {

	 		Properties options = new Properties();

	 		if (theme != null) {
	 			options.setProperty(PROPERTY_THEME, theme);
	 		}
	 		if (tabindex != null) {
	 			options.setProperty(PROPERTY_TABINDEX, String.valueOf(tabindex));
	 		}

	 		return createRecaptchaHtml(errorMessage, options);
	 	}

	 	/**
	 	 * Produces javascript array with the RecaptchaOptions encoded.
	 	 * 
	 	 * @param properties
	 	 * @return
	 	 */
	 	private String fetchJSOptions(Properties properties) {

	 		if (properties == null || properties.size() == 0) {
	 			return "";
	 		}

	 		String jsOptions =
	 			"<script type=\"text/javascript\">\r\n" + 
	 			"var RecaptchaOptions = {";
	 			
	 		for (Enumeration e = properties.keys(); e.hasMoreElements(); ) {
	 			String property = (String) e.nextElement();
	 			
	 			jsOptions += property + ":'" + properties.getProperty(property)+"'";
	 			
	 			if (e.hasMoreElements()) {
	 				jsOptions += ",";
	 			}
	 			
	 		}

	 		jsOptions += "};\r\n</script>\r\n";

	 		return jsOptions;
	 	}

}
